import mysql from "mysql2/promise";
import {Config, Dict, Transformer} from "./types.js";
import {genFile as plainGenFile} from "./generators/plain-generator.js";
import dmdb, {Metadata} from "dmdb";

export async function generate(config: Config) {
    if (!config.transformer) {
        config.transformer = defaultTransformer(config.columns);
    }

    // fetch data
    let rows: Object[] | null = null;
    if (config.database.type === 'mysql') {
        rows = await fetchFromMysql(config);
    } else if (config.database.type === 'dm') {
        rows = await fetchFromDM(config);
    }

    // transform rows
    if (rows) {
        const dict = config.transformer(rows);
        // write to file
        if (config.outType === 'js') {
            await plainGenFile(config.outPath, config.outType, dict)
        } else if (config.outType === 'ts') {
            await plainGenFile(config.outPath, config.outType, dict)
        }
    }
    console.log("generate success")
}

async function initMysqlClient(config: Config) {
    const mysqlConfig = config.database;
    const connection = await mysql.createConnection({
        host: mysqlConfig.host,
        port: mysqlConfig.port,
        user: mysqlConfig.user,
        password: mysqlConfig.password,
        database: mysqlConfig.database,
    });
    return connection;
}

async function fetchFromMysql(config: Config): Promise<Object[] | null> {
    const connection = await initMysqlClient(config)
    const mysqlConfig = config.database;
    try {
        const [results, fields] = await connection.query(
            `select *
             from \`${mysqlConfig.table}\``,
        );

        // console.log(results); // results contains rows returned by server
        // console.log(fields); // fields contains extra meta data about results, if available
        return results as Object[];
    } catch (err) {
        console.log(err);
    } finally {
        connection.destroy()
    }
    return null;
}

async function fetchFromDM(config: Config): Promise<Object[] | null> {
    const dmConfig = config.database
    const pool = await dmdb.createPool({
        connectString: `dm://${dmConfig.user}:${dmConfig.password}@${dmConfig.host}:${dmConfig.port}/${dmConfig.database}?loginEncrypt=false`,
        poolMax: 10,
        poolMin: 1,
    })
    const con = await pool.getConnection()
    const result = await con.execute(`select *
                                      from ${dmConfig.database}.${dmConfig.table}`);
    await con.close()
    await pool.close()
    const res = result.rows?.map((item) => {
        let res: any = {}
        result.metaData?.forEach((col: Metadata | Metadata[], idx: number) => {
            const metadata = col as Metadata
            res[metadata.name] = (item as any[])[idx]
        })
        return res;
    }) as Object[]
    return res;
}

function defaultTransformer(columns: Config['columns']): Transformer {
    let colConf: Required<Config>['columns'] = columns!;
    if (!columns) {
        colConf = {
            name: 'dictionary_type',
            comment: 'dictionary_memo',
            label: 'dictionary_value',
            value: 'dictionary_code'
        }
    }

    return (rows: Object[]) => {
    const map = new Map();
    rows.forEach((item: any) => {
        const dictionType = item[colConf.name] as string;
        const dict = map.get(dictionType);
        if (!dict) {
            map.set(dictionType, {
                name: dictionType,
                comment: item[colConf.comment],
                select: [
                    {label: item[colConf.label], value: item[colConf.value]},
                ],
            } as Dict);
        } else {
            dict.select.push({
                label: item[colConf.label],
                value: item[colConf.value],
            });
        }
    });

    return Array.from(map.values());
    }
}

// (async function main() {
//     await generate({
//         genPath: "src/dict",
//         mysqlConfig: {
//             host: "localhost",
//             port: 3306,
//             user: "root",
//             password: "softwise",
//             database: "test",
//             table: "t_dictionary",
//         },
//     });
// })();
